# -*- coding:utf-8 -*-
import datetime
from flask import request,g,jsonify,current_app,session
from iHome.models import Area,Facility,User,House,HouseImage, Order
from . import api
from iHome import constants
from iHome import redis_store,db
from iHome.utils.response_code import RET
from iHome.constants import AREA_INFO_REDIS_EXPIRES,QINIU_DOMIN_PREFIX,HOUSE_DETAIL_REDIS_EXPIRE_SECOND,HOME_PAGE_MAX_HOUSES,HOME_PAGE_DATA_REDIS_EXPIRES,HOUSE_LIST_PAGE_CAPACITY
from iHome.utils.common import login_required
from iHome.utils.storage_image import storage_image


@api.route('.houses')
def search_house():
    '''
    var params = {
        aid:areaId,
        sd:startDate,
        ed:endDate,
        sk:sortKey,
        p:next_page
    };
    :return:
    '''
    args = request.args
    aid = args.get("aid", "")
    start_date_str = args.get("sd", "")
    end_date_str = args.get("ed", "")
    # new最新上线，booking 入住最多，price-inc 价格 低>高，price-des 价格 高>低
    sk = args.get("sk", "new")
    p = args.get("p", "1")

    # 判断参数
    start_date = None
    end_date = None
    try:
        if start_date_str:
            start_date = datetime.datetime.strptime(start_date_str,"%Y-%m-%d")
        if end_date_str:
            end_date = datetime.datetime.strptime(end_date_str,"%Y-%m-%d")
        if end_date and start_date:
            assert start_date < end_date,Exception("开始时间不能大于结束时间")
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg="参数错误")

    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmag="参数有误")

    # 从redis中读取房屋数据
    try:
        redis_key = "house_list_%s_%s_%s_%s"%(aid,start_date_str,end_date_str,sk)
        response_dict = redis_store.hget(redis_key,p)
        if response_dict:
            return jsonify(errno=RET.OK,errmsg="OK",data=eval(response_dict))
    except Exception as e:
        current_app.logger.error(e)


    # 先把所有的房屋都查询出来并返回
    try:
        house_query = House.query
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据失败')

    # 过滤条件的列表
    filters = []
    if aid:
        # 添加过滤条件
        filters.append(House.area-id == aid)


    # 定义冲突的订单
    conflict_order = None

    if start_date and end_date:
        conflict_order = Order.query.filter(Order.begin_date < end_date, Order.end_date > start_date).all()
    elif start_date:
        conflict_order = Order.query.filter(Order.end_date > start_date).all()
    elif end_date:
        conflict_order = Order.query.filter(Order.begin_date < end_date).all()

    if conflict_order:
        # 取到这些冲突订单的房屋id >
        conflict_house_ids = [order.house_id for order in conflict_order]
        # 不包含冲突订单的房屋id数据
        filters.append(House.id.notin_(conflict_house_ids))
    # 根据不同排序方式去查
    if sk == "booking":
        house_query = house_query.filter(*filters).order_by(House.order_count.desc())
    elif sk == "price-inc":
        house_query = house_query.filter(*filters).order_by(House.price)
    elif sk == "price-des":
        house_query = house_query.filter(*filters).order_by(House.price.desc())
    else:
        house_query = house_query.filter(*filters).order_by(House.create_time.desc())
    # 获取到分页对象:参数1:第几页数据,参数2:每一页有多少个,参数3:是否输出错误
    paginate = house_query.paginate(int(p),HOUSE_LIST_PAGE_CAPACITY,False)
    # 取到当前页的所有对象
    houses = paginate.items
    # 记录总页数
    total_page = paginate.pages


    houses_dict = []
    for house in houses:
        houses_dict.append(house.to_basic_dict())

    # return jsonify(errno=RET.OK, errmsg="OK", data={"houses": houses_dict, "total_page": total_page})
    response_dict = {"houses":houses_dict,"total_page":total_page}

    # 保存房屋数据
    if p <= total_page:  # 当前页如果小鱼或者等于总页数,再去存
        try:
            redis_key = "house_list_%s_%s_%s_%s"%(aid,start_date_str,end_date_str, sk)
            # 获取到管道操作
            pipe = redis_store.pipeline()
            # 开启事务
            pipe.multi()
            # 设置数据
            pipe.hset(redis_key,constants.HOUSE_LIST_REDIS_EXPIRES)
            # 提交事务
            pipe.execute()
        except Exception as e:
            current_app.logger.error(e)
    return jsonify(errno=RET.OK,errmsg="OK",data=response_dict)

@api.route('/houses/index')
def get_houses_index():
    """
    首页推荐的房屋最多5个,以订单数量来排序
    :return:
    """
    # 尝试从缓存中取
    try:
        houses_dict = redis_store.get("home_house_index")
        if houses_dict:
            return jsonify(errno=RET.OK,errmsg="OK",data=eval(houses_dict))
    except Exception as e:
        current_app.logger.error(e)

    # 查询房屋数据:以订单号倒序排序,最前5个
    try:
        houses = House.query.order_by(House.order_count.desc())
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg="查询数据失败")

    houses_dict = []
    if houses:
        for house in houses:
            houses_dict.append(house.to_basic_dict())

        # 去缓存数据
        try:
            redis_store.set("home_house_index",houses_dict,HOME_PAGE_DATA_REDIS_EXPIRES)
        except Exception as e:
            current_app.logger.error(e)

        return jsonify(errno=RET.OK,errmsg="OK",data=houses_dict)

    return jsonify(errno=RET.OK,errmsg="OK",data=houses_dict)




@api.route("/houses/<int:house_id>")
def get_house_datail(house_id):
    """
    1. 通过house_id查询出房屋
    2. 将房屋模型的数据封装到字典中,user_id(取到当前登录用户的id,如果用户没有登录,值为-1表示未登录)
    3. 直接返回
    4. 将房屋数据缓存到redis中
    :param house_id:
    :return:
    """
    user_id = session.get("user_id")
    # 去读取
    try:
        house_dict = redis_store.get("house_deatil_%d" % house_id)
        if house_dict:
            return jsonify(errno=RET.OK,errmsg="OK",data={"user_id":user_id,"house":eval(house_dict)})
    except Exception as e:
        current_app.logger.error(e)

    # 通过房屋id查找到具体的房屋信息

    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg="数据查询失败")

    if not house:
        return jsonify(errno=RET.NODATA,errmsg="房屋不存在")

    # 生成要返回的信息
    house_dict = house.to_full_dict()

    # 去缓存
    try:
        redis_store.set(("house_deatil_%d" % house_id),house_dict,HOUSE_DETAIL_REDIS_EXPIRE_SECOND)
    except Exception as e:
        current_app.logger.error(e)

    return jsonify(errno=RET.OK,errmsg="OK",data={"user_id":user_id,"house":house_dict})



@api.route('/house/<int:house_id>/images',methods=["POST"])
@login_required
def upload_house_image(house_id):
    """    1. 取到参数，house_id，要上传的图片
     2. 查询对应的ｉｄ房屋
     3. 再上传图片
     4. 保存图片，判断房屋的首页图片是否有值，如果没有值，设置
    :return:
    """
    try:
        house_image_file = request.files.get("house_image").read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg="参数错误")

    # 2. 查询是否有指定房屋
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询房屋信息失败')

    # 3. 上传图片
    try:
        url = storage_image(house_image_file)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erron=RET.THIRDERR,errmsg="上传图片失败")


    # 4. 初始化模型
    house_image = HouseImage()
    house_image.house_id = house.id
    house_image.url = url
    try:
        # 设置房屋的头图
        if not house.index_image_url:
            house.index_image_url = url

        db.session.add(house_image)
        db.session.commit()

    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.OK,errmsg="OK",data={"url":QINIU_DOMIN_PREFIX + url})





@api.route("/house",methods=['POST'])
@login_required
def save_new_house():
    """
    1. 获取上传的参数
    2.　判断是否为空
    3.　初始化一个House的对象
    4.　进行数据保存
    5.　返回结果／／／
    """
    # 1. 获取上传的参数
    user_id = g.user_id
    json_dict = request.json
    title = json_dict.get('title')
    price = json_dict.get('price')
    address = json_dict.get('address')
    area_id = json_dict.get('area_id')
    room_count = json_dict.get('room_count')
    acreage = json_dict.get('acreage')
    unit = json_dict.get('unit')
    capacity = json_dict.get('capacity')
    beds = json_dict.get('beds')
    deposit = json_dict.get('deposit')
    min_days = json_dict.get('min_days')
    max_days = json_dict.get('max_days')

    # 2. 判断是否为空，校验参数
    if not all(
            [title, price, address, area_id, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')

    try:
        price = int(float(price) * 100)
        deposit = int(float(deposit) * 100)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')

    # 3. 初始化house对象
    house = House()

    house.user_id = user_id
    house.area_id = area_id
    house.title = title
    house.price = price
    house.address = address
    house.room_count = room_count
    house.acreage = acreage
    house.unit = unit
    house.capacity = capacity
    house.beds = beds
    house.deposit = deposit
    house.min_days = min_days
    house.max_days = max_days

    # 设置房屋设施
    facilities = json_dict.get("facility")
    if facilities:
        # 查询指定列表中对应的模型并设置设施信息
        house.facilities = Facility.query.filter(Facility.id.in_(facilities)).all()

    # 4. 进行数据保存
    try:
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="添加数据失败")

    return jsonify(errno=RET.OK, errmsg="ok", data={"house_id": house.id})


@api.route('/areas')
def get_areas():
    '''获取城区信息'''
    # 0. 先从redis中取
    try:
        areas_array = redis_store.get("areas")
        if areas_array:
            return jsonify(errno=RET.OK,errmsg="OK",data={"areas":eval(areas_array)})
    except Exception as e:
        current_app.logger.error(e)
    # 1. 获取所有的城区信息
    areas = Area.query.all()

    # 2. 因为　areas 是一个对象的列表，不能直接返回，需要将其转成字典的列表
    areas_array = []
    for area in areas:
        areas_array.append(area.to_dict())

    # 3. 将数据缓存到redis中
    try:
        redis_store.set("areas",areas_array,AREA_INFO_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)

    # 4. 返回数据
    return jsonify(errno=RET.OK,errmsg="OK",data={"areas":areas_array})











